package com.lintf.flowable.controller;

import com.lintf.common.base.AjaxResult;
import com.lintf.common.page.BaseController;
import com.lintf.flowable.dto.ProcessDevelopDTO;
import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.ProcessEngine;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

/**
 * Flowable开发流程管理控制器
 * 提供启动、查询和管理流程实例的端点
 * <p>
 * 作者: 林廷锋
 * 系统: Mac
 * 日期: 2025/1/20
 * 包名: com.lintf.flowable.controller
 * 项目名: sharding-sphere
 */
@Slf4j
@RestController
@RequestMapping("/flowable/development")
public class FlowableDevelopmentController extends BaseController {

    private final RuntimeService runtimeService;
    private final TaskService taskService;
    private final RepositoryService repositoryService;
    private final ProcessEngine processEngine;

    private final String processDefinitionKey = "myProcess";

    @Autowired
    public FlowableDevelopmentController(RuntimeService runtimeService, TaskService taskService, RepositoryService repositoryService, ProcessEngine processEngine) {
        this.runtimeService = runtimeService;
        this.taskService = taskService;
        this.repositoryService = repositoryService;
        this.processEngine = processEngine;
    }

    /**
     * 启动一个新的流程实例
     *
     * @param dto 包含流程详细信息的ProcessDTO
     * @return 包含流程实例ID的AjaxResult
     */
    @PostMapping("/startProcess")
    public AjaxResult startProcess(ProcessDevelopDTO dto) {
        Map<String, Object> variables = new HashMap<>();
        variables.put("name", dto.getName());
        variables.put("author", dto.getAuthor());
        variables.put("assignee", dto.getAuthor());
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinitionKey, variables);
        runtimeService.updateBusinessStatus(processInstance.getId(), "待开发");
        log.info("流程实例ID：{}", processInstance.getId());
        return AjaxResult.success(processInstance.getId());
    }

    /**
     * 提交流程实例到下一个阶段
     *
     * @param dto 包含流程实例ID和开发人员信息的ProcessDTO
     * @return 包含流程实例ID的AjaxResult
     */
    @PostMapping("/submitProcess")
    public AjaxResult submitProcess(ProcessDevelopDTO dto) {
        String processInstanceId = dto.getProcessInstanceId();
        log.info("流程实例ID：" + processInstanceId);
        Task task = taskService.createTaskQuery().processInstanceId(processInstanceId).singleResult();
        Map<String, Object> variables = new HashMap<>();
        variables.put("developer", dto.getDeveloper());
        variables.put("assignee", dto.getDeveloper());
        taskService.complete(task.getId(), variables);
        runtimeService.updateBusinessStatus(processInstanceId, "开发中");
        String result = String.format("流程id:%s,任务id:%s,状态:%s", processInstanceId, task.getId(), "开发中");
        log.info(result);
        return AjaxResult.success("流程实例ID：" + processInstanceId);
    }

    /**
     * 完成开发任务并将流程转移到测试阶段
     *
     * @param dto 包含流程实例ID和开发人员信息的ProcessDTO
     * @return 包含流程实例ID的AjaxResult
     */
    @PostMapping("/completeDevelop")
    public AjaxResult completeDevelop(ProcessDevelopDTO dto) {
        String processInstanceId = dto.getProcessInstanceId();
        log.info("流程实例ID：" + processInstanceId);
        Task task = taskService.createTaskQuery().processInstanceId(processInstanceId).taskAssignee(dto.getDeveloper()).singleResult();
        Map<String, Object> variables = new HashMap<>();
        variables.put("developer", dto.getDeveloper());
        variables.put("assignee", dto.getTester());
        variables.put("result", null); // 清除之前的测试结果
        taskService.complete(task.getId(), variables);
        runtimeService.updateBusinessStatus(processInstanceId, "测试中");
        String result = String.format("流程id:%s,任务id:%s,状态:%s", processInstanceId, task.getId(), "测试中");
        log.info(result);
        return AjaxResult.success("流程实例ID：" + processInstanceId);
    }

    /**
     * 完成测试任务并将流程状态更新为“测试通过”
     *
     * @param dto 包含流程实例ID和测试人员信息的ProcessDTO
     * @return 包含流程实例ID的AjaxResult
     */
    @PostMapping("/completeTest")
    public AjaxResult completeTest(ProcessDevelopDTO dto) {
        String processInstanceId = dto.getProcessInstanceId();
        log.info("流程实例ID：" + processInstanceId);
        Task task = taskService.createTaskQuery().processInstanceId(processInstanceId).taskAssignee(dto.getTester()).singleResult();
        Map<String, Object> variables = new HashMap<>();
        variables.put("tester", dto.getTester());
        variables.put("result", true);
        runtimeService.updateBusinessStatus(processInstanceId, "测试通过");
        taskService.complete(task.getId(), variables);
        String result = String.format("流程id:%s,任务id:%s,状态:%s", processInstanceId, task.getId(), "测试通过");
        log.info(result);
        return AjaxResult.success("流程实例ID：" + processInstanceId);
    }

    /**
     * 拒绝测试并将流程退回到开发阶段
     *
     * @param dto 包含流程实例ID和测试人员信息的ProcessDTO
     * @return 包含流程实例ID的AjaxResult
     */
    @PostMapping("/refuseTest")
    public AjaxResult refuseTest(ProcessDevelopDTO dto) {
        String processInstanceId = dto.getProcessInstanceId();
        log.info("流程实例ID：" + processInstanceId);
        Task task = taskService.createTaskQuery().processInstanceId(processInstanceId).taskAssignee(dto.getTester()).singleResult();
        Map<String, Object> taskServiceVariables = taskService.getVariables(task.getId());
        Map<String, Object> variables = new HashMap<>();
        Object developer = taskServiceVariables.get("developer");
        variables.put("developer", developer);
        variables.put("assignee", developer);
        variables.put("result", false);
        runtimeService.updateBusinessStatus(processInstanceId, "测试返工");
        taskService.complete(task.getId(), variables);
        String result = String.format("流程id:%s,任务id:%s,状态:%s", processInstanceId, task.getId(), "测试返工");
        log.info(result);
        return AjaxResult.success("流程实例ID：" + processInstanceId);
    }

}